home *** CD-ROM | disk | FTP | other *** search
- Subject: v21i088: Safely rename wildcarded files, Part02/02
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: fbb8a4a2 cf48eba6 238c816b ae51c752
-
- Submitted-by: Vladimir Lanin <lanin@csd4.cs.nyu.edu>
- Posting-number: Volume 21, Issue 88
- Archive-name: mmv/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: mmv.c.1
- # Wrapped by rsalz@litchi.bbn.com on Mon Apr 9 17:05:23 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mmv.c.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mmv.c.1'\"
- else
- echo shar: Extracting \"'mmv.c.1'\" \(49841 characters\)
- sed "s/^X//" >'mmv.c.1' <<'END_OF_FILE'
- X/*
- X mmv 1.0
- X Copyright (c) 1990 Vladimir Lanin.
- X This program may be freely used and copied on a non-commercial basis.
- X The author assumes no responsibility for any damage or data loss that may
- X result from the use of this program.
- X
- X Author may be reached at:
- X
- X lanin@csd4.nyu.edu
- X
- X Vladimir Lanin
- X 330 Wadsworth Ave, Apt 6F,
- X New York, NY 10040
- X*/
- X
- X/*
- X Define SYSV to compile under System V.
- X If your System V has a rename() call, define RENAME.
- X Otherwise, mmv will only be able to rename directories (via option -r)
- X when running as the super-user.
- X There is no reason to set the suid bit on mmv if rename() is available.
- X It is important that mmv not be run with effective uid set
- X to any value other than either the real uid or the super-user.
- X Even when running with effective uid set to super-user,
- X mmv will only perform actions permitted to the real uid.
- X
- X Define MSDOS to compile under MS-D*S Turbo C 1.5.
- X If you prefer mmv's output to use /'s instead of \'s under MS-D*S,
- X define SLASH.
- X
- X When neither MSDOS nor SYSV are defined, compiles under BSD.
- X
- X RENAME is automatically defined under MSDOS and BSD.
- X
- X If you are running a (UN*X) system that provides the
- X "struct dirent" readdir() directory reading standard,
- X define DIRENT. Otherwise, mmv uses the BSD-like
- X "struct direct" readdir().
- X If your (UN*X) system has neither of these, get the "dirent"
- X by Doug Gwyn, available as gwyn-dir-lib in volume 9
- X of the comp.sources.unix archives.
- X*/
- X
- Xstatic char USAGE[] =
- X#ifdef MSDOS
- X
- X"Usage: \
- X%s [-m|x%s|c|o|a|z] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
- X\n\
- XUse =N in the ``to'' pattern to get the string matched\n\
- Xby the N'th ``from'' pattern wildcard.\n";
- X
- X#define OTHEROPT (_osmajor < 3 ? "" : "|r")
- X
- X#else
- X
- X"Usage: \
- X%s [-m|x|r|c|o|a|l%s] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
- X\n\
- XUse =[l|u]N in the ``to'' pattern to get the [lowercase|uppercase of the]\n\
- Xstring matched by the N'th ``from'' pattern wildcard.\n\
- X\n\
- XA ``from'' pattern containing wildcards should be quoted when given\n\
- Xon the command line.\n";
- X
- X#ifdef SYSV
- X#define OTHEROPT ""
- X#else
- X#define OTHEROPT "|s"
- X#endif
- X
- X#endif
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <string.h>
- X
- X#ifdef MSDOS
- X/* for MS-DOS (under Turbo C 1.5)*/
- X
- X#include <stdlib.h>
- X#include <sys/stat.h>
- X#include <dos.h>
- X#include <dir.h>
- X#include <io.h>
- X#include <fcntl.h>
- X
- X#define ESC '\''
- X#ifdef SLASH
- X#define SLASH '/'
- X#define OTHERSLASH '\\'
- X#else
- X#define SLASH '\\'
- X#define OTHERSLASH '/'
- X#endif
- X
- Xtypedef int DIRID;
- Xtypedef int DEVID;
- X
- Xstatic char TTY[] = "/dev/con";
- Xextern unsigned _stklen = 10000;
- X
- X#define RENAME
- X
- X#else
- X/* for various flavors of UN*X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X#include <sys/signal.h>
- X#include <fcntl.h>
- Xextern char *getenv();
- Xextern long lseek();
- Xextern char *malloc();
- X
- X#ifdef DIRENT
- X#include <dirent.h>
- Xtypedef struct dirent DIRENTRY;
- X#else
- X#ifdef SYSV
- X#include <sys/dir.h>
- X/* might need to be changed to <dir.h> */
- X#else
- X#include <sys/dir.h>
- X#endif
- Xtypedef struct direct DIRENTRY;
- X#endif
- X
- X#define void char /* might want to remove this line */
- X
- X#ifndef O_BINARY
- X#define O_BINARY 0
- X#endif
- X#ifndef R_OK
- X#define R_OK 4
- X#define W_OK 2
- X#define X_OK 1
- X#endif
- X
- X#define ESC '\\'
- X#define SLASH '/'
- X
- Xtypedef ino_t DIRID;
- Xtypedef dev_t DEVID;
- X
- X#define MAXPATH 1024
- X
- Xstatic char TTY[] = "/dev/tty";
- X
- X#ifdef SYSV
- X/* for System V */
- X
- Xstruct utimbuf {
- X time_t actime;
- X time_t modtime;
- X};
- X#define utimes(f, t) utime((f), (t))
- X
- X
- X#else
- X/* for BSD */
- X
- X#define RENAME
- X
- X#include <sys/time.h>
- X
- X#endif
- X
- X#endif
- X
- X
- X#define mylower(c) (isupper(c) ? (c)-'A'+'a' : (c))
- X#define myupper(c) (islower(c) ? (c)-'a'+'A' : (c))
- X#define STRLEN(s) (sizeof(s) - 1)
- X#define mydup(s) (strcpy((char *)challoc(strlen(s) + 1, 0), (s)))
- X
- X
- X#define DFLT 0x001
- X#define NORMCOPY 0x002
- X#define OVERWRITE 0x004
- X#define NORMMOVE 0x008
- X#define XMOVE 0x010
- X#define DIRMOVE 0x020
- X#define NORMAPPEND 0x040
- X#define ZAPPEND 0x080
- X#define HARDLINK 0x100
- X#define SYMLINK 0x200
- X
- X#define COPY (NORMCOPY | OVERWRITE)
- X#define MOVE (NORMMOVE | XMOVE | DIRMOVE)
- X#define APPEND (NORMAPPEND | ZAPPEND)
- X#define LINK (HARDLINK | SYMLINK)
- X
- Xstatic char MOVENAME[] = "mmv";
- Xstatic char COPYNAME[] = "mcp";
- Xstatic char APPENDNAME[] = "mad";
- Xstatic char LINKNAME[] = "mln";
- X
- X#define ASKDEL 0
- X#define ALLDEL 1
- X#define NODEL 2
- X
- X#define ASKBAD 0
- X#define SKIPBAD 1
- X#define ABORTBAD 2
- X
- X#define STAY 0
- X#define LOWER 1
- X#define UPPER 2
- X
- X#define MAXWILD 20
- X#define MAXPATLEN MAXPATH
- X#define INITROOM 10
- X#define CHUNKSIZE 2048
- X#define BUFSIZE 4096
- X
- X#define FI_STTAKEN 0x01
- X#define FI_LINKERR 0x02
- X#define FI_INSTICKY 0x04
- X#define FI_NODEL 0x08
- X#define FI_KNOWWRITE 0x010
- X#define FI_CANWRITE 0x20
- X#define FI_ISDIR 0x40
- X#define FI_ISLNK 0x80
- X
- Xtypedef struct {
- X char *fi_name;
- X struct rep *fi_rep;
- X#ifdef MSDOS
- X char fi_attrib;
- X#else
- X short fi_mode;
- X char fi_stflags;
- X#endif
- X} FILEINFO;
- X
- X#define DI_KNOWWRITE 0x01
- X#define DI_CANWRITE 0x02
- X#define DI_CLEANED 0x04
- X
- Xtypedef struct {
- X DEVID di_vid;
- X DIRID di_did;
- X unsigned di_nfils;
- X FILEINFO **di_fils;
- X char di_flags;
- X} DIRINFO;
- X
- X#define H_NODIR 1
- X#define H_NOREADDIR 2
- X
- Xtypedef struct {
- X char *h_name;
- X DIRINFO *h_di;
- X char h_err;
- X} HANDLE;
- X
- X#define R_ISX 0x01
- X#define R_SKIP 0x02
- X#define R_DELOK 0x04
- X#define R_ISALIASED 0x08
- X#define R_ISCYCLE 0x10
- X#define R_ONEDIRLINK 0x20
- X
- Xtypedef struct rep {
- X HANDLE *r_hfrom;
- X FILEINFO *r_ffrom;
- X HANDLE *r_hto;
- X char *r_nto; /* non-path part of new name */
- X FILEINFO *r_fdel;
- X struct rep *r_first;
- X struct rep *r_thendo;
- X struct rep *r_next;
- X char r_flags;
- X} REP;
- X
- Xtypedef struct {
- X REP *rd_p;
- X DIRINFO *rd_dto;
- X char *rd_nto;
- X unsigned rd_i;
- X} REPDICT;
- X
- Xtypedef struct chunk {
- X struct chunk *ch_next;
- X unsigned ch_len;
- X} CHUNK;
- X
- Xtypedef struct {
- X CHUNK *sl_first;
- X char *sl_unused;
- X int sl_len;
- X} SLICER;
- X
- X
- Xstatic void init(/* */);
- Xstatic void procargs(/* int argc, char **argv,
- X char **pfrompat, char **ptopat */);
- Xstatic void matchpats(/* char *cfrom, char *cto */);
- Xstatic int getpat(/* */);
- Xstatic int getword(/* char *buf */);
- Xstatic void matchpat(/* */);
- Xstatic int parsepat(/* */);
- Xstatic int dostage(/* char *lastend, char *pathend,
- X char **start1, int *len1, int stage, int anylev */);
- Xstatic int trymatch(/* FILEINFO *ffrom, char *pat */);
- Xstatic int keepmatch(/* FILEINFO *ffrom, char *pathend,
- X int *pk, int needslash, int dirs, int fils */);
- Xstatic int badrep(/* HANDLE *hfrom, FILEINFO *ffrom,
- X HANDLE **phto, char **pnto, FILEINFO **pfdel, int *pflags */);
- Xstatic int checkto(/* HANDLE *hfrom, char *f,
- X HANDLE **phto, char **pnto, FILEINFO **pfdel */);
- Xstatic char *getpath(/* char *tpath */);
- Xstatic int badname(/* char *s */);
- Xstatic FILEINFO *fsearch(/* char *s, DIRINFO *d */);
- Xstatic int ffirst(/* char *s, int n, DIRINFO *d */);
- Xstatic HANDLE *checkdir(/* char *p, char *pathend, int which */);
- Xstatic void takedir(/*
- X char *p, DIRINFO *di, int sticky
- Xor
- X struct ffblk *pff, DIRINFO *di
- X*/);
- Xstatic int fcmp(/* FILEINFO **pf1, FILEINFO **pf2 */);
- Xstatic HANDLE *hadd(/* char *n */);
- Xstatic int hsearch(/* char *n, int which, HANDLE **ph */);
- Xstatic DIRINFO *dadd(/* DEVID v, DIRID d */);
- Xstatic DIRINFO *dsearch(/* DEVID v, DIRID d */);
- Xstatic int match(/* char *pat, char *s, char **start1, int *len1 */);
- Xstatic void makerep(/* */);
- Xstatic void checkcollisions(/* */);
- Xstatic int rdcmp(/* REPDICT *rd1, REPDICT *rd2 */);
- Xstatic void findorder(/* */);
- Xstatic void scandeletes(/* int (*pkilldel)(REP *p) */);
- Xstatic int baddel(/* REP *p */);
- Xstatic int skipdel(/* REP *p */);
- Xstatic void nochains(/* */);
- Xstatic void printchain(/* REP *p */);
- Xstatic void goonordie(/* */);
- Xstatic void doreps(/* */);
- Xstatic long appendalias(/* REP *first, REP *p, int *pprintaliased */);
- Xstatic int movealias(/* REP *first, REP *p, int *pprintaliased */);
- Xstatic int snap(/* REP *first, REP *p */);
- Xstatic void showdone(/* REP *fin */);
- Xstatic void breakout(/* */);
- Xstatic int breakrep(/* */);
- Xstatic void breakstat(/* */);
- Xstatic void quit(/* */);
- Xstatic int copymove(/* REP *p */);
- Xstatic int copy(/* FILENFO *f, long len */);
- Xstatic int myunlink(/* char *n, FILEINFO *f */);
- Xstatic int getreply(/* char *m, int failact */);
- Xstatic void *myalloc(/* unsigned k */);
- Xstatic void *challoc(/* int k, int which */);
- Xstatic void chgive(/* void *p, unsigned k */);
- Xstatic int mygetc(/* */);
- X#ifdef MSDOS
- Xstatic int leave(/* */);
- Xstatic void cleanup(/* */);
- X#else
- Xstatic int getstat(/* char *full, FILEINFO *f */);
- Xstatic int dwritable(/* HANDLE *h */);
- Xstatic int fwritable(/* char *hname, FILEINFO *f */);
- Xstatic void memmove(/* void *to, void *from, int k */);
- X#endif
- X#ifndef RENAME
- Xstatic int rename(/* char *from, char *to */);
- X#endif
- X
- Xstatic int op, badstyle, delstyle, verbose, noex, matchall;
- Xstatic int patflags;
- X
- Xstatic unsigned ndirs = 0, dirroom;
- Xstatic DIRINFO **dirs;
- Xstatic unsigned nhandles = 0, handleroom;
- Xstatic HANDLE **handles;
- Xstatic HANDLE badhandle = {"\200", NULL, 0};
- Xstatic HANDLE *(lasthandle[2]) = {&badhandle, &badhandle};
- Xstatic unsigned nreps = 0;
- Xstatic REP hrep, *lastrep = &hrep;
- Xstatic CHUNK *freechunks = NULL;
- Xstatic SLICER slicer[2] = {{NULL, NULL, 0}, {NULL, NULL, 0}};
- X
- Xstatic int badreps = 0, paterr = 0, direrr, failed = 0, gotsig = 0, repbad;
- Xstatic FILE *outfile = stdout;
- X
- Xstatic char IDF[] = "$$mmvdid.";
- Xstatic char TEMP[] = "$$mmvtmp.";
- Xstatic char TOOLONG[] = "(too long)";
- Xstatic char EMPTY[] = "(empty)";
- X
- Xstatic char SLASHSTR[] = {SLASH, '\0'};
- X
- Xstatic char PATLONG[] = "%.40s... : pattern too long.\n";
- X
- Xstatic char from[MAXPATLEN], to[MAXPATLEN];
- Xstatic int fromlen, tolen;
- Xstatic char *(stagel[MAXWILD]), *(firstwild[MAXWILD]), *(stager[MAXWILD]);
- Xstatic int nwilds[MAXWILD];
- Xstatic int nstages;
- Xstatic char pathbuf[MAXPATH];
- Xstatic char fullrep[MAXPATH + 1];
- Xstatic char *(start[MAXWILD]);
- Xstatic int len[MAXWILD];
- Xstatic char hasdot[MAXWILD];
- Xstatic REP mistake;
- X#define MISTAKE (&mistake)
- X
- X#ifdef MSDOS
- X
- Xstatic int olddevflag, curdisk, maxdisk;
- Xstatic struct {
- X char ph_banner[30];
- X char ph_name[9];
- X int ph_dfltop;
- X int ph_safeid;
- X int ph_clustoff;
- X int ph_driveoff;
- X int ph_drivea;
- X} patch = {"mmv 1.0 patchable flags", "mmv", XMOVE, 1, 0};
- X
- X#define DFLTOP (patch.ph_dfltop)
- X#define CLUSTNO(pff) (*(int *)(((char *)(pff)) + patch.ph_clustoff))
- X#define DRIVENO(pff) (*(((char *)(pff)) + patch.ph_driveoff) - patch.ph_drivea)
- X
- X
- X#else
- X
- X#define DFLTOP XMOVE
- X
- Xstatic char *home;
- Xstatic int homelen;
- Xstatic int uid, euid, oldumask;
- Xstatic DIRID cwdd = -1;
- Xstatic DEVID cwdv = -1;
- X
- X#endif
- X
- X
- Xint main(argc, argv)
- X int argc;
- X char *(argv[]);
- X{
- X char *frompat, *topat;
- X
- X init();
- X procargs(argc, argv, &frompat, &topat);
- X matchpats(frompat, topat);
- X if (!(op & APPEND))
- X checkcollisions();
- X findorder();
- X if (op & (COPY | LINK))
- X nochains();
- X scandeletes(baddel);
- X goonordie();
- X if (!(op & APPEND) && delstyle == ASKDEL)
- X scandeletes(skipdel);
- X doreps();
- X return(failed ? 2 : nreps == 0 && (paterr || badreps));
- X}
- X
- X
- Xstatic void init()
- X{
- X#ifdef MSDOS
- X curdisk = getdisk();
- X maxdisk = setdisk(curdisk);
- X/*
- X Read device availability : undocumented internal MS-DOS function.
- X If (_DX == 0) then \dev\ must precede device names.
- X*/
- X bdos(0x37, 0, 2);
- X olddevflag = _DX;
- X/*
- X Write device availability: undocumented internal MS-DOS function.
- X Specify \dev\ must precede device names.
- X*/
- X bdos(0x37, 0, 3);
- X atexit((atexit_t)cleanup);
- X ctrlbrk((int (*)())breakout);
- X#else
- X struct stat dstat;
- X
- X if ((home = getenv("HOME")) == NULL || strcmp(home, SLASHSTR) == 0)
- X home = "";
- X if (!stat(".", &dstat)) {
- X cwdd = dstat.st_ino;
- X cwdv = dstat.st_dev;
- X }
- X oldumask = umask(0);
- X euid = geteuid();
- X uid = getuid();
- X signal(SIGINT, breakout);
- X#endif
- X
- X dirroom = handleroom = INITROOM;
- X dirs = (DIRINFO **)myalloc(dirroom * sizeof(DIRINFO *));
- X handles = (HANDLE **)myalloc(handleroom * sizeof(HANDLE *));
- X ndirs = nhandles = 0;
- X}
- X
- X
- Xstatic void procargs(argc, argv, pfrompat, ptopat)
- X int argc;
- X char **argv;
- X char **pfrompat, **ptopat;
- X{
- X char *p, c;
- X char *cmdname = argv[0];
- X
- X#ifdef MSDOS
- X#define CMDNAME (patch.ph_name)
- X#else
- X#define CMDNAME cmdname
- X#endif
- X
- X op = DFLT;
- X verbose = noex = matchall = 0;
- X delstyle = ASKDEL;
- X badstyle = ASKBAD;
- X for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++)
- X for (p = *argv + 1; *p != '\0'; p++) {
- X c = mylower(*p);
- X if (c == 'v' && !noex)
- X verbose = 1;
- X else if (c == 'n' && !verbose)
- X noex = 1;
- X else if (c == 'h')
- X matchall = 1;
- X else if (c == 'd' && delstyle == ASKDEL)
- X delstyle = ALLDEL;
- X else if (c == 'p' && delstyle == ASKDEL)
- X delstyle = NODEL;
- X else if (c == 'g' && badstyle == ASKBAD)
- X badstyle = SKIPBAD;
- X else if (c == 't' && badstyle == ASKBAD)
- X badstyle = ABORTBAD;
- X else if (c == 'm' && op == DFLT)
- X op = NORMMOVE;
- X else if (c == 'x' && op == DFLT)
- X op = XMOVE;
- X else if (c == 'r' && op == DFLT)
- X op = DIRMOVE;
- X else if (c == 'c' && op == DFLT)
- X op = NORMCOPY;
- X else if (c == 'o' && op == DFLT)
- X op = OVERWRITE;
- X else if (c == 'a' && op == DFLT)
- X op = NORMAPPEND;
- X#ifdef MSDOS
- X else if (c == 'z' && op == DFLT)
- X op = ZAPPEND;
- X#else
- X else if (c == 'l' && op == DFLT)
- X op = HARDLINK;
- X#ifndef SYSV
- X else if (c == 's' && op == DFLT)
- X op = SYMLINK;
- X#endif
- X#endif
- X else {
- X fprintf(stderr, USAGE, CMDNAME, OTHEROPT);
- X exit(1);
- X }
- X }
- X
- X if (op == DFLT)
- X if (strcmp(cmdname, MOVENAME) == 0)
- X op = XMOVE;
- X else if (strcmp(cmdname, COPYNAME) == 0)
- X op = NORMCOPY;
- X else if (strcmp(cmdname, APPENDNAME) == 0)
- X op = NORMAPPEND;
- X else if (strcmp(cmdname, LINKNAME) == 0)
- X op = HARDLINK;
- X else
- X op = DFLTOP;
- X if (
- X op & DIRMOVE &&
- X#ifdef MSDOS
- X _osmajor < 3
- X#else
- X#ifndef RENAME
- X euid != 0
- X#else
- X 0
- X#endif
- X#endif
- X ) {
- X fprintf(stderr,
- X "Unable to do directory renames. Option -r refused.\n");
- X quit();
- X }
- X
- X#ifndef MSDOS
- X if (euid != uid && !(op & DIRMOVE)) {
- X setuid(uid);
- X setgid(getgid());
- X }
- X#endif
- X
- X if (badstyle != ASKBAD && delstyle == ASKDEL)
- X delstyle = NODEL;
- X
- X if (argc == 0)
- X *pfrompat = NULL;
- X else if (argc == 2) {
- X *pfrompat = *(argv++);
- X *ptopat = *(argv++);
- X }
- X else {
- X fprintf(stderr, USAGE, CMDNAME, OTHEROPT);
- X exit(1);
- X }
- X}
- X
- X
- Xstatic void matchpats(cfrom, cto)
- X char *cfrom, *cto;
- X{
- X if (cfrom == NULL)
- X while (getpat())
- X matchpat();
- X else if ((fromlen = strlen(cfrom)) >= MAXPATLEN) {
- X printf(PATLONG, cfrom);
- X paterr = 1;
- X }
- X else if ((tolen = strlen(cto)) >= MAXPATLEN) {
- X printf(PATLONG, cto);
- X paterr = 1;
- X }
- X else {
- X strcpy(from, cfrom);
- X strcpy(to, cto);
- X matchpat();
- X }
- X}
- X
- X
- Xstatic int getpat()
- X{
- X int c, gotit = 0;
- X char extra[MAXPATLEN];
- X
- X patflags = 0;
- X do {
- X if ((fromlen = getword(from)) == 0 || fromlen == -1)
- X goto nextline;
- X
- X do {
- X if ((tolen = getword(to)) == 0) {
- X printf("%s -> ? : missing replacement pattern.\n", from);
- X goto nextline;
- X }
- X if (tolen == -1)
- X goto nextline;
- X } while (
- X tolen == 2 &&
- X (to[0] == '-' || to[0] == '=') &&
- X (to[1] == '>' || to[1] == '^')
- X );
- X if (getword(extra) == 0)
- X gotit = 1;
- X else if (strcmp(extra, "(*)") == 0) {
- X patflags |= R_DELOK;
- X gotit = (getword(extra) == 0);
- X }
- X
- Xnextline:
- X while ((c = mygetc()) != '\n' && c != EOF)
- X ;
- X if (c == EOF)
- X return(0);
- X } while (!gotit);
- X
- X return(1);
- X}
- X
- X
- Xstatic int getword(buf)
- X char *buf;
- X{
- X int c, prevc, n;
- X char *p;
- X
- X p = buf;
- X prevc = ' ';
- X n = 0;
- X while ((c = mygetc()) != EOF && (prevc == ESC || !isspace(c))) {
- X if (n == -1)
- X continue;
- X if (n == MAXPATLEN - 1) {
- X *p = '\0';
- X printf(PATLONG, buf);
- X n = -1;
- X }
- X *(p++) = c;
- X n++;
- X prevc = c;
- X }
- X *p = '\0';
- X while (c != EOF && isspace(c) && c != '\n')
- X c = mygetc();
- X if (c != EOF)
- X ungetc(c, stdin);
- X return(n);
- X}
- X
- X
- Xstatic void matchpat()
- X{
- X if (parsepat())
- X paterr = 1;
- X else if (dostage(from, pathbuf, start, len, 0, 0)) {
- X printf("%s -> %s : no match.\n", from, to);
- X paterr = 1;
- X }
- X}
- X
- X
- Xstatic int parsepat()
- X{
- X char *p, *lastname, c;
- X int totwilds, instage, x, havedot;
- X static char TRAILESC[] = "%s -> %s : trailing %c is superfluous.\n";
- X
- X lastname = from;
- X#ifdef MSDOS
- X havedot = 0;
- X if (from[0] != '\0' && from[1] == ':')
- X lastname += 2;
- X#else
- X if (from[0] == '~' && from[1] == SLASH) {
- X if ((homelen = strlen(home)) + fromlen > MAXPATLEN) {
- X printf(PATLONG, from);
- X return(-1);
- X }
- X memmove(from + homelen, from + 1, fromlen);
- X memmove(from, home, homelen);
- X lastname += homelen + 1;
- X }
- X#endif
- X totwilds = nstages = instage = 0;
- X for (p = lastname; (c = *p) != '\0'; p++)
- X switch (c) {
- X#ifdef MSDOS
- X case '.':
- X havedot = 1;
- X break;
- X case OTHERSLASH:
- X *p = SLASH;
- X#endif
- X case SLASH:
- X#ifdef MSDOS
- X if (!havedot && lastname != p) {
- X if (fromlen++ == MAXPATLEN) {
- X printf(PATLONG, from);
- X return(-1);
- X }
- X memmove(p + 1, p, strlen(p) + 1);
- X *(p++) = '.';
- X }
- X else
- X havedot = 0;
- X#endif
- X lastname = p + 1;
- X if (instage) {
- X if (firstwild[nstages] == NULL)
- X firstwild[nstages] = p;
- X stager[nstages++] = p;
- X instage = 0;
- X }
- X break;
- X case ';':
- X if (lastname != p) {
- X printf("%s -> %s : badly placed ;.\n", from, to);
- X return(-1);
- X }
- X case '!':
- X case '*':
- X case '?':
- X case '[':
- X#ifdef MSDOS
- X if ((hasdot[totwilds] = (c == '!')) != 0)
- X havedot = 1;
- X#endif
- X if (totwilds++ == MAXWILD) {
- X printf("%s -> %s : too many wildcards.\n", from, to);
- X return(-1);
- X }
- X if (instage) {
- X nwilds[nstages]++;
- X if (firstwild[nstages] == NULL)
- X firstwild[nstages] = p;
- X }
- X else {
- X stagel[nstages] = lastname;
- X firstwild[nstages] = (c == ';' ? NULL : p);
- X nwilds[nstages] = 1;
- X instage = 1;
- X }
- X if (c != '[')
- X break;
- X while ((c = *(++p)) != ']') {
- X switch (c) {
- X case '\0':
- X printf("%s -> %s : missing ].\n", from, to);
- X return(-1);
- X#ifdef MSDOS
- X case '.':
- X case ':':
- X case OTHERSLASH:
- X#endif
- X case SLASH:
- X printf("%s -> %s : '%c' can not be part of [].\n",
- X from, to, c);
- X return(-1);
- X case ESC:
- X if ((c = *(++p)) == '\0') {
- X printf(TRAILESC, from, to, ESC);
- X return(-1);
- X }
- X#ifdef MSDOS
- X default:
- X if (isupper(c))
- X *p = c + ('a' - 'A');
- X#endif
- X }
- X }
- X break;
- X case ESC:
- X if ((c = *(++p)) == '\0') {
- X printf(TRAILESC, from, to, ESC);
- X return(-1);
- X }
- X#ifdef MSDOS
- X default:
- X if (isupper(c))
- X *p = c + ('a' - 'A');
- X#endif
- X }
- X
- X#ifdef MSDOS
- X if (!havedot && lastname != p) {
- X if (fromlen++ == MAXPATLEN) {
- X printf(PATLONG, from);
- X return(-1);
- X }
- X strcpy(p++, ".");
- X }
- X#endif
- X
- X if (instage) {
- X if (firstwild[nstages] == NULL)
- X firstwild[nstages] = p;
- X stager[nstages++] = p;
- X }
- X else {
- X stagel[nstages] = lastname;
- X nwilds[nstages] = 0;
- X firstwild[nstages] = p;
- X stager[nstages++] = p;
- X }
- X
- X lastname = to;
- X#ifdef MSDOS
- X havedot = 0;
- X if (to[0] != '\0' && to[1] == ':')
- X lastname += 2;
- X#else
- X if (to[0] == '~' && to[1] == SLASH) {
- X if ((homelen = strlen(home)) + tolen > MAXPATLEN) {
- X printf(PATLONG, to);
- X return(-1);
- X }
- X memmove(to + homelen, to + 1, tolen);
- X memmove(to, home, homelen);
- X lastname += homelen + 1;
- X }
- X#endif
- X
- X for (p = lastname; (c = *p) != '\0'; p++)
- X switch (c) {
- X#ifdef MSDOS
- X case '.':
- X havedot = 1;
- X break;
- X case OTHERSLASH:
- X *p = SLASH;
- X#endif
- X case SLASH:
- X if (op & DIRMOVE) {
- X printf("%s -> %s : no path allowed in target under -r.\n",
- X from, to);
- X return(-1);
- X }
- X#ifdef MSDOS
- X if (!havedot && lastname != p) {
- X if (tolen++ == MAXPATLEN) {
- X printf(PATLONG, to);
- X return(-1);
- X }
- X memmove(p + 1, p, strlen(p) + 1);
- X *(p++) = '.';
- X }
- X else
- X havedot = 0;
- X#endif
- X lastname = p + 1;
- X break;
- X case '=':
- X c = *(++p);
- X if (c == 'l' || c == 'u') {
- X#ifdef MSDOS
- X strcpy(p, p + 1);
- X c = *p;
- X#else
- X c = *(++p);
- X#endif
- X }
- X if (!isdigit(c)) {
- X printf("%s -> %s : expected digit (not '%c') after =.\n",
- X from, to, c);
- X return(-1);
- X }
- X for(x = 0; ;x *= 10) {
- X x += c - '0';
- X c = *(p+1);
- X if (!isdigit(c))
- X break;
- X p++;
- X }
- X if (x < 1 || x > totwilds) {
- X printf("%s -> %s : wildcard %d does not exist.\n",
- X from, to, x);
- X return(-1);
- X }
- X#ifdef MSDOS
- X if (hasdot[x - 1])
- X havedot = 1;
- X#endif
- X break;
- X case ESC:
- X if ((c = *(++p)) == '\0') {
- X printf(TRAILESC, from, to, ESC);
- X return(-1);
- X }
- X default:
- X if (
- X#ifdef MSDOS
- X c <= ' ' || c >= 127 ||
- X strchr(":/\\*?[]=+;,\"|<>", c) != NULL
- X#else
- X c & 0x80
- X#endif
- X ) {
- X printf("%s -> %s : illegal character '%c' (0x%02X).\n",
- X from, to, c, c);
- X return(-1);
- X }
- X#ifdef MSDOS
- X if (isupper(c))
- X *p = c + ('a' - 'A');
- X#endif
- X }
- X
- X#ifdef MSDOS
- X if (!havedot && lastname != p) {
- X if (tolen++ == MAXPATLEN) {
- X printf(PATLONG, to);
- X return(-1);
- X }
- X strcpy(p++, ".");
- X }
- X#endif
- X
- X return(0);
- X}
- X
- X
- Xstatic int dostage(lastend, pathend, start1, len1, stage, anylev)
- X char *lastend, *pathend;
- X char **start1;
- X int *len1;
- X int stage;
- X int anylev;
- X{
- X DIRINFO *di;
- X HANDLE *h, *hto;
- X int prelen, litlen, nfils, i, k, flags, try;
- X FILEINFO **pf, *fdel;
- X char *nto, *firstesc;
- X REP *p;
- X int wantdirs, ret = 1, laststage = (stage + 1 == nstages);
- X
- X wantdirs = !laststage ||
- X (op & (DIRMOVE | SYMLINK)) ||
- X (nwilds[nstages - 1] == 0);
- X
- X if (!anylev) {
- X prelen = stagel[stage] - lastend;
- X if (pathend - pathbuf + prelen >= MAXPATH) {
- X printf("%s -> %s : search path after %s too long.\n",
- X from, to, pathbuf);
- X paterr = 1;
- X return(1);
- X }
- X memmove(pathend, lastend, prelen);
- X pathend += prelen;
- X *pathend = '\0';
- X lastend = stagel[stage];
- X }
- X
- X if ((h = checkdir(pathbuf, pathend, 0)) == NULL) {
- X if (stage == 0 || direrr == H_NOREADDIR) {
- X printf("%s -> %s : directory %s does not %s.\n",
- X from, to, pathbuf, direrr == H_NOREADDIR ?
- X "allow reads/searches" : "exist");
- X paterr = 1;
- X }
- X return(stage);
- X }
- X di = h->h_di;
- X
- X if (*lastend == ';') {
- X anylev = 1;
- X *start1 = pathend;
- X *len1 = 0;
- X lastend++;
- X }
- X
- X nfils = di->di_nfils;
- X
- X#ifndef MSDOS
- X if ((op & MOVE) && !dwritable(h)) {
- X printf("%s -> %s : directory %s does not allow writes.\n",
- X from, to, pathbuf);
- X paterr = 1;
- X goto skiplev;
- X }
- X#endif
- X
- X firstesc = strchr(lastend, ESC);
- X if (firstesc == NULL || firstesc > firstwild[stage])
- X firstesc = firstwild[stage];
- X litlen = firstesc - lastend;
- X pf = di->di_fils + (i = ffirst(lastend, litlen, di));
- X if (i < nfils)
- X do {
- X if (
- X (try = trymatch(*pf, lastend)) != 0 &&
- X (
- X try == 1 ||
- X match(lastend + litlen, (*pf)->fi_name + litlen,
- X start1 + anylev, len1 + anylev)
- X ) &&
- X keepmatch(*pf, pathend, &k, 0, wantdirs, laststage)
- X ) {
- X if (!laststage)
- X ret &= dostage(stager[stage], pathend + k,
- X start1 + nwilds[stage], len1 + nwilds[stage],
- X stage + 1, 0);
- X else {
- X ret = 0;
- X makerep();
- X if (badrep(h, *pf, &hto, &nto, &fdel, &flags))
- X (*pf)->fi_rep = MISTAKE;
- X else {
- X (*pf)->fi_rep = p = (REP *)challoc(sizeof(REP), 1);
- X p->r_flags = flags | patflags;
- X p->r_hfrom = h;
- X p->r_ffrom = *pf;
- X p->r_hto = hto;
- X p->r_nto = nto;
- X p->r_fdel = fdel;
- X p->r_first = p;
- X p->r_thendo = NULL;
- X p->r_next = NULL;
- X lastrep->r_next = p;
- X lastrep = p;
- X nreps++;
- X }
- X }
- X }
- X i++, pf++;
- X } while (i < nfils && strncmp(lastend, (*pf)->fi_name, litlen) == 0);
- X
- Xskiplev:
- X if (anylev)
- X for (pf = di->di_fils, i = 0; i < nfils; i++, pf++)
- X if (
- X *((*pf)->fi_name) != '.' &&
- X#ifdef MSDOS
- X ((*pf)->fi_attrib & FA_DIREC) &&
- X#endif
- X keepmatch(*pf, pathend, &k, 1, 1, 0)
- X ) {
- X *len1 = pathend - *start1 + k;
- X ret &= dostage(lastend, pathend + k, start1, len1, stage, 1);
- X }
- X
- X return(ret);
- X}
- X
- X
- Xstatic int trymatch(ffrom, pat)
- X FILEINFO *ffrom;
- X char *pat;
- X{
- X char *p;
- X
- X if (ffrom->fi_rep != NULL)
- X return(0);
- X
- X p = ffrom->fi_name;
- X
- X#ifdef MSDOS
- X if (*p == '.' || (!matchall && ffrom->fi_attrib & (FA_HIDDEN | FA_SYSTEM)))
- X return(strcmp(pat, p) == 0);
- X#else
- X if (*p == '.')
- X if (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))
- X return(strcmp(pat, p) == 0);
- X else if (!matchall && *pat != '.')
- X return(0);
- X#endif
- X return(-1);
- X}
- X
- X
- Xstatic int keepmatch(ffrom, pathend, pk, needslash, dirs, fils)
- X FILEINFO *ffrom;
- X char *pathend;
- X int *pk;
- X int needslash;
- X int dirs, fils;
- X{
- X *pk = strlen(ffrom->fi_name);
- X if (pathend - pathbuf + *pk + needslash >= MAXPATH) {
- X *pathend = '\0';
- X printf("%s -> %s : search path %s%s too long.\n",
- X from, to, pathbuf, ffrom->fi_name);
- X paterr = 1;
- X return(0);
- X }
- X strcpy(pathend, ffrom->fi_name);
- X#ifdef MSDOS
- X if ((ffrom->fi_attrib & FA_DIREC) ? !dirs : !fils)
- X#else
- X getstat(pathbuf, ffrom);
- X if ((ffrom->fi_stflags & FI_ISDIR) ? !dirs : !fils)
- X#endif
- X return(0);
- X
- X if (needslash) {
- X strcpy(pathend + *pk, SLASHSTR);
- X (*pk)++;
- X }
- X return(1);
- X}
- X
- X
- Xstatic int badrep(hfrom, ffrom, phto, pnto, pfdel, pflags)
- X HANDLE *hfrom;
- X FILEINFO *ffrom;
- X HANDLE **phto;
- X char **pnto;
- X FILEINFO **pfdel;
- X int *pflags;
- X{
- X char *f = ffrom->fi_name;
- X
- X *pflags = 0;
- X if (
- X#ifdef MSDOS
- X (ffrom->fi_attrib & FA_DIREC) &&
- X#else
- X (ffrom->fi_stflags & FI_ISDIR) &&
- X#endif
- X !(op & (DIRMOVE | SYMLINK))
- X )
- X printf("%s -> %s : source file is a directory.\n", pathbuf, fullrep);
- X#ifndef MSDOS
- X#ifndef SYSV
- X else if ((ffrom->fi_stflags & FI_LINKERR) && !(op & (MOVE | SYMLINK)))
- X printf("%s -> %s : source file is a badly aimed symbolic link.\n",
- X pathbuf, fullrep);
- X else if ((ffrom->fi_stflags & FI_NODEL) && (op & MOVE))
- X printf("%s -> %s : no delete permission for source file.\n",
- X pathbuf, fullrep);
- X#endif
- X else if ((op & (COPY | APPEND)) && access(pathbuf, R_OK))
- X printf("%s -> %s : no read permission for source file.\n",
- X pathbuf, fullrep);
- X#endif
- X else if (
- X *f == '.' &&
- X (f[1] == '\0' || strcmp(f, "..") == 0) &&
- X !(op & SYMLINK)
- X )
- X printf("%s -> %s : . and .. can't be renamed.\n", pathbuf, fullrep);
- X else if (repbad || checkto(hfrom, f, phto, pnto, pfdel) || badname(*pnto))
- X printf("%s -> %s : bad new name.\n", pathbuf, fullrep);
- X else if (*phto == NULL)
- X printf("%s -> %s : %s.\n", pathbuf, fullrep,
- X#ifndef MSDOS
- X direrr == H_NOREADDIR ?
- X "no read or search permission for target directory" :
- X#endif
- X "target directory does not exist");
- X#ifndef MSDOS
- X else if (!dwritable(*phto))
- X printf("%s -> %s : no write permission for target directory.\n",
- X pathbuf, fullrep);
- X#endif
- X else if (
- X (*phto)->h_di->di_vid != hfrom->h_di->di_vid &&
- X (*pflags = R_ISX, (op & (NORMMOVE | HARDLINK)))
- X )
- X printf("%s -> %s : cross-device move.\n",
- X pathbuf, fullrep);
- X#ifndef MSDOS
- X else if (
- X *pflags && (op & MOVE) &&
- X !(ffrom->fi_stflags & FI_ISLNK) &&
- X access(pathbuf, R_OK)
- X )
- X printf("%s -> %s : no read permission for source file.\n",
- X pathbuf, fullrep);
- X#ifndef SYSV
- X else if (
- X (op & SYMLINK) &&
- X !(
- X ((*phto)->h_di->di_vid == cwdv && (*phto)->h_di->di_did == cwdd) ||
- X *(hfrom->h_name) == SLASH ||
- X (*pflags |= R_ONEDIRLINK, hfrom->h_di == (*phto)->h_di)
- X )
- X )
- X printf("%s -> %s : symbolic link would be badly aimed.\n",
- X pathbuf, fullrep);
- X#endif
- X#endif
- X else
- X return(0);
- X badreps++;
- X return(-1);
- X}
- X
- X
- Xstatic int checkto(hfrom, f, phto, pnto, pfdel)
- X HANDLE *hfrom;
- X char *f;
- X HANDLE **phto;
- X char **pnto;
- X FILEINFO **pfdel;
- X{
- X char tpath[MAXPATH + 1];
- X char *pathend;
- X FILEINFO *fdel;
- X int hlen, tlen;
- X
- X if (op & DIRMOVE) {
- X *phto = hfrom;
- X hlen = strlen(hfrom->h_name);
- X pathend = fullrep + hlen;
- X memmove(pathend, fullrep, strlen(fullrep) + 1);
- X memmove(fullrep, hfrom->h_name, hlen);
- X if ((fdel = *pfdel = fsearch(pathend, hfrom->h_di)) != NULL) {
- X *pnto = fdel->fi_name;
- X#ifndef MSDOS
- X getstat(fullrep, fdel);
- X#endif
- X }
- X else
- X *pnto = mydup(pathend);
- X }
- X else {
- X pathend = getpath(tpath);
- X hlen = pathend - fullrep;
- X *phto = checkdir(tpath, tpath + hlen, 1);
- X if (
- X *phto != NULL &&
- X *pathend != '\0' &&
- X (fdel = *pfdel = fsearch(pathend, (*phto)->h_di)) != NULL &&
- X#ifdef MSDOS
- X (fdel->fi_attrib & FA_DIREC)
- X#else
- X (getstat(fullrep, fdel), fdel->fi_stflags & FI_ISDIR)
- X#endif
- X ) {
- X tlen = strlen(pathend);
- X strcpy(pathend + tlen, SLASHSTR);
- X tlen++;
- X strcpy(tpath + hlen, pathend);
- X pathend += tlen;
- X hlen += tlen;
- X *phto = checkdir(tpath, tpath + hlen, 1);
- X }
- X
- X if (*pathend == '\0') {
- X *pnto = f;
- X if (pathend - fullrep + strlen(f) >= MAXPATH) {
- X strcpy(fullrep, TOOLONG);
- X return(-1);
- X }
- X strcat(pathend, f);
- X if (*phto != NULL) {
- X fdel = *pfdel = fsearch(f, (*phto)->h_di);
- X#ifndef MSDOS
- X if (fdel != NULL)
- X getstat(fullrep, fdel);
- X#endif
- X }
- X }
- X else if (fdel != NULL)
- X *pnto = fdel->fi_name;
- X else
- X *pnto = mydup(pathend);
- X }
- X return(0);
- X}
- X
- X
- Xstatic char *getpath(tpath)
- X char *tpath;
- X{
- X char *pathstart, *pathend, c;
- X
- X#ifdef MSDOS
- X if (*fullrep != '\0' && fullrep[1] == ':')
- X pathstart = fullrep + 2;
- X else
- X#endif
- X pathstart = fullrep;
- X
- X pathend = pathstart + strlen(pathstart) - 1;
- X while (pathend >= pathstart && *pathend != SLASH)
- X --pathend;
- X pathend++;
- X
- X c = *pathend;
- X *pathend = '\0';
- X strcpy(tpath, fullrep);
- X *pathend = c;
- X return(pathend);
- X}
- X
- X
- Xstatic int badname(s)
- X char *s;
- X{
- X char *ext;
- X
- X return (
- X#ifdef MSDOS
- X *s == ' ' ||
- X *s == '.' ||
- X (ext = strchr(s, '.')) - s >= MAXFILE ||
- X (*ext == '.' && strchr(ext + 1, '.') != NULL) ||
- X strlen(ext) >= MAXEXT ||
- X strncmp(s, IDF, STRLEN(IDF)) == 0
- X#else
- X (*s == '.' && (s[1] == '\0' || strcmp(s, "..") == 0)) ||
- X strlen(s) > MAXNAMLEN
- X#endif
- X );
- X}
- X
- X
- X#ifndef MSDOS
- Xstatic int getstat(ffull, f)
- X char *ffull;
- X FILEINFO *f;
- X{
- X struct stat fstat;
- X int flags;
- X
- X if ((flags = f->fi_stflags) & FI_STTAKEN)
- X return(flags & FI_LINKERR);
- X flags |= FI_STTAKEN;
- X#ifdef SYSV
- X if (stat(ffull, &fstat)) {
- X fprintf("Strange, couldn't stat %s.\n", ffull);
- X quit();
- X }
- X#else
- X if (lstat(ffull, &fstat)) {
- X fprintf("Strange, couldn't lstat %s.\n", ffull);
- X quit();
- X }
- X if ((flags & FI_INSTICKY) && fstat.st_uid != uid && uid != 0)
- X flags |= FI_NODEL;
- X if ((fstat.st_mode & S_IFMT) == S_IFLNK) {
- X flags |= FI_ISLNK;
- X if (stat(ffull, &fstat)) {
- X f->fi_stflags = flags | FI_LINKERR;
- X return(1);
- X }
- X }
- X#endif
- X if ((fstat.st_mode & S_IFMT) == S_IFDIR)
- X flags |= FI_ISDIR;
- X f->fi_stflags = flags;
- X f->fi_mode = fstat.st_mode;
- X return(0);
- X}
- X
- X
- Xstatic int dwritable(h)
- X HANDLE *h;
- X{
- X char *p = h->h_name, *myp, *lastslash = NULL, *pathend;
- X char *pw = &(h->h_di->di_flags), r;
- X
- X if (uid == 0)
- X return(1);
- X
- X if (*pw & DI_KNOWWRITE)
- X return(*pw & DI_CANWRITE);
- X
- X pathend = p + strlen(p);
- X if (*p == '\0')
- X myp = ".";
- X else if (pathend == p + 1)
- X myp = SLASHSTR;
- X else {
- X lastslash = pathend - 1;
- X *lastslash = '\0';
- X myp = p;
- X }
- X r = !access(myp, W_OK) ? DI_CANWRITE : 0;
- X *pw |= DI_KNOWWRITE | r;
- X
- X if (lastslash != NULL)
- X *lastslash = SLASH;
- X return(r);
- X}
- X
- X
- Xstatic int fwritable(hname, f)
- X char *hname;
- X FILEINFO *f;
- X{
- X int r;
- X
- X if (f->fi_stflags & FI_KNOWWRITE)
- X return(f->fi_stflags & FI_CANWRITE);
- X
- X strcpy(fullrep, hname);
- X strcat(fullrep, f->fi_name);
- X r = !access(fullrep, W_OK) ? FI_CANWRITE : 0;
- X f->fi_stflags |= FI_KNOWWRITE | r;
- X return(r);
- X}
- X#endif
- X
- X
- Xstatic FILEINFO *fsearch(s, d)
- X char *s;
- X DIRINFO *d;
- X{
- X FILEINFO **fils = d->di_fils;
- X int nfils = d->di_nfils;
- X int first, k, last, res;
- X
- X for(first = 0, last = nfils - 1;;) {
- X if (last < first)
- X return(NULL);
- X k = (first + last) >> 1;
- X if ((res = strcmp(s, fils[k]->fi_name)) == 0)
- X return(fils[k]);
- X if (res < 0)
- X last = k - 1;
- X else
- X first = k + 1;
- X }
- X}
- X
- X
- Xstatic int ffirst(s, n, d)
- X char *s;
- X int n;
- X DIRINFO *d;
- X{
- X int first, k, last, res;
- X FILEINFO **fils = d->di_fils;
- X int nfils = d->di_nfils;
- X
- X if (nfils == 0 || n == 0)
- X return(0);
- X first = 0;
- X last = nfils - 1;
- X for(;;) {
- X k = (first + last) >> 1;
- X res = strncmp(s, fils[k]->fi_name, n);
- X if (first == last)
- X return(res == 0 ? k : nfils);
- X else if (res > 0)
- X first = k + 1;
- X else
- X last = k;
- X }
- X}
- X
- X
- X#ifdef MSDOS
- X/* checkdir and takedir for MS-D*S */
- X
- Xstatic HANDLE *checkdir(p, pathend, which)
- X char *p, *pathend;
- X int which;
- X{
- X struct ffblk de;
- X DIRID d;
- X DEVID v;
- X HANDLE *h;
- X char *dirstart = p;
- X int fd;
- X int firstfound;
- X DIRINFO *di;
- X
- X if (hsearch(p, which, &h))
- X if (h->h_di == NULL) {
- X direrr = h->h_err;
- X return(NULL);
- X }
- X else
- X return(h);
- X
- X if (*p == '\0' || p[1] != ':')
- X v = curdisk;
- X else {
- X dirstart += 2;
- X v = mylower(p[0]) - 'a';
- X if (v < 0 || v >= maxdisk)
- X return(NULL);
- X }
- X
- X if (patch.ph_safeid) {
- X strcpy(pathend, IDF);
- X strcpy(pathend + STRLEN(IDF), "*");
- X if (findfirst(p, &de, 0)) {
- X if ((d = ndirs) == 1000) {
- X fprintf(stderr, "Too many different directories.\n");
- X quit();
- X }
- X sprintf(pathend + STRLEN(IDF), "%03d", d);
- X if ((fd = _creat(p, 0)) < 0) {
- X direrr = h->h_err = H_NODIR;
- X return(NULL);
- X }
- X _close(fd);
- X strcpy(pathend, "*.*");
- X if (findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN))
- X h->h_di = dadd(v, d);
- X else
- X takedir(&de, h->h_di = dadd(v, d));
- X }
- X else if ((d = atoi(de.ff_name + STRLEN(IDF))) < ndirs)
- X h->h_di = dirs[d];
- X else {
- X strcpy(pathend, de.ff_name);
- X fprintf(stderr, "Strange dir-id file encountered: %s.\n", p);
- X quit();
- X }
- X *pathend = '\0';
- X }
- X else {
- X strcpy(pathend, "*.*");
- X firstfound = !findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN);
- X *pathend = '\0';
- X if (firstfound) {
- X v = DRIVENO(&de);
- X d = CLUSTNO(&de);
- X }
- X else {
- X strcpy(pathend, "T.D");
- X if (mkdir(p)) {
- X *pathend = '\0';
- X direrr = h->h_err = H_NODIR;
- X return(NULL);
- X }
- X strcpy(pathend, "*.*");
- X firstfound = !findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN);
- X *pathend = '\0';
- X v = DRIVENO(&de);
- X d = CLUSTNO(&de);
- X rmdir(p);
- X if (!firstfound || d != 0) {
- X fprintf(stderr,
- X "Strange, %s does not seem to be a root dir.\n",
- X p);
- X quit();
- X }
- X }
- X
- X if ((di = dsearch(v, d)) == NULL)
- X if (firstfound)
- X takedir(&de, h->h_di = dadd(v, d));
- X else
- X h->h_di = dadd(v, d);
- X else
- X h->h_di = di;
- X }
- X
- X return(h);
- X}
- X
- X
- Xstatic void takedir(pff, di)
- X struct ffblk *pff;
- X DIRINFO *di;
- X{
- X int cnt, room, namlen, needdot;
- X FILEINFO **fils, *f;
- X char c, *p, *p1;
- X
- X room = INITROOM;
- X di->di_fils = fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- X cnt = 0;
- X do {
- X if (strnicmp(pff->ff_name, IDF, STRLEN(IDF)) == 0)
- X continue;
- X if (cnt == room) {
- X room *= 2;
- X fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- X memcpy(fils, di->di_fils, cnt * sizeof(FILEINFO *));
- X chgive(di->di_fils, cnt * sizeof(FILEINFO *));
- X di->di_fils = fils;
- X fils = di->di_fils + cnt;
- X }
- X needdot = 1;
- X for (p = pff->ff_name, namlen = 0; (c = *p) != '\0'; p++, namlen++)
- X if (c == '.')
- X needdot = 0;
- X *fils = f = (FILEINFO *)challoc(sizeof(FILEINFO), 1);
- X f->fi_name = p = (char *)challoc(namlen + needdot + 1, 0);
- X for (p1 = pff->ff_name; (c = *p1) != '\0'; p1++)
- X *(p++) = mylower(c);
- X if (needdot)
- X *(p++) = '.';
- X *p = '\0';
- X f->fi_attrib = pff->ff_attrib;
- X f->fi_rep = NULL;
- X cnt++;
- X fils++;
- X } while (findnext(pff) == 0);
- X qsort(di->di_fils, cnt, sizeof(FILEINFO *), fcmp);
- X di->di_nfils = cnt;
- X}
- X
- X#else
- X/* checkdir, takedir for Un*x */
- X
- Xstatic HANDLE *checkdir(p, pathend, which)
- X char *p, *pathend;
- X int which;
- X{
- X struct stat dstat;
- X DIRID d;
- X DEVID v;
- X DIRINFO **newdirs, *di;
- X int nfils;
- X FILEINFO **fils;
- X char *myp, *lastslash = NULL;
- X int sticky;
- X HANDLE *h;
- X
- X if (hsearch(p, which, &h))
- X if (h->h_di == NULL) {
- X direrr = h->h_err;
- X return(NULL);
- X }
- X else
- X return(h);
- X
- X if (*p == '\0')
- X myp = ".";
- X else if (pathend == p + 1)
- X myp = SLASHSTR;
- X else {
- X lastslash = pathend - 1;
- X *lastslash = '\0';
- X myp = p;
- X }
- X
- X if (stat(myp, &dstat) || (dstat.st_mode & S_IFMT) != S_IFDIR)
- X direrr = h->h_err = H_NODIR;
- X else if (access(myp, R_OK | X_OK))
- X direrr = h->h_err = H_NOREADDIR;
- X else {
- X direrr = 0;
- X sticky = (dstat.st_mode & S_ISVTX) && uid != 0 && uid != dstat.st_uid ?
- X FI_INSTICKY : 0;
- X v = dstat.st_dev;
- X d = dstat.st_ino;
- X
- X if ((di = dsearch(v, d)) == NULL)
- X takedir(myp, di = dadd(v, d), sticky);
- X }
- X
- X if (lastslash != NULL)
- X *lastslash = SLASH;
- X if (direrr != 0)
- X return(NULL);
- X h->h_di = di;
- X return(h);
- X}
- X
- X
- Xstatic void takedir(p, di, sticky)
- X char *p;
- X DIRINFO *di;
- X int sticky;
- X{
- X int cnt, room;
- X DIRENTRY *dp;
- X FILEINFO *f, **fils;
- X DIR *dirp;
- X
- X if ((dirp = opendir(p)) == NULL) {
- X fprintf(stderr, "Strange, can't scan %s.\n", p);
- X quit();
- X }
- X room = INITROOM;
- X di->di_fils = fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- X cnt = 0;
- X while ((dp = readdir(dirp)) != NULL) {
- X if (cnt == room) {
- X room *= 2;
- X fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- X memcpy(fils, di->di_fils, cnt * sizeof(FILEINFO *));
- X chgive(di->di_fils, cnt * sizeof(FILEINFO *));
- X di->di_fils = fils;
- X fils = di->di_fils + cnt;
- X }
- X *fils = f = (FILEINFO *)challoc(sizeof(FILEINFO), 1);
- X f->fi_name = mydup(dp->d_name);
- X f->fi_stflags = sticky;
- X f->fi_rep = NULL;
- X cnt++;
- X fils++;
- X }
- X closedir(dirp);
- X qsort(di->di_fils, cnt, sizeof(FILEINFO *), fcmp);
- X di->di_nfils = cnt;
- X}
- X
- X/* end of Un*x checkdir, takedir; back to general program */
- X#endif
- X
- X
- Xstatic int fcmp(pf1, pf2)
- X FILEINFO **pf1, **pf2;
- X{
- X return(strcmp((*pf1)->fi_name, (*pf2)->fi_name));
- X}
- X
- X
- Xstatic HANDLE *hadd(n)
- X char *n;
- X{
- X HANDLE **newhandles, *h;
- X
- X if (nhandles == handleroom) {
- X handleroom *= 2;
- X newhandles = (HANDLE **)myalloc(handleroom * sizeof(HANDLE *));
- X memcpy(newhandles, handles, nhandles * sizeof(HANDLE *));
- X chgive(handles, nhandles * sizeof(HANDLE *));
- X handles = newhandles;
- X }
- X handles[nhandles++] = h = (HANDLE *)challoc(sizeof(HANDLE), 1);
- X h->h_name = (char *)challoc(strlen(n) + 1, 0);
- X strcpy(h->h_name, n);
- X h->h_di = NULL;
- X return(h);
- X}
- X
- X
- Xstatic int hsearch(n, which, pret)
- X char *n;
- X int which;
- X HANDLE **pret;
- X{
- X int i;
- X HANDLE **ph;
- X
- X if (strcmp(n, lasthandle[which]->h_name) == 0) {
- X *pret = lasthandle[which];
- X return(1);
- X }
- X
- X for(i = 0, ph = handles; i < nhandles; i++, ph++)
- X if (strcmp(n, (*ph)->h_name) == 0) {
- X lasthandle[which] = *pret = *ph;
- X return(1);
- X }
- X
- X lasthandle[which] = *pret = hadd(n);
- X return(0);
- X}
- X
- X
- Xstatic DIRINFO *dadd(v, d)
- X DEVID v;
- X DIRID d;
- X{
- X DIRINFO *di;
- X DIRINFO **newdirs;
- X
- X if (ndirs == dirroom) {
- X dirroom *= 2;
- X newdirs = (DIRINFO **)myalloc(dirroom * sizeof(DIRINFO *));
- X memcpy(newdirs, dirs, ndirs * sizeof(DIRINFO *));
- X chgive(dirs, ndirs * sizeof(DIRINFO *));
- X dirs = newdirs;
- X }
- X dirs[ndirs++] = di = (DIRINFO *)challoc(sizeof(DIRINFO), 1);
- X di->di_vid = v;
- X di->di_did = d;
- X di->di_nfils = 0;
- X di->di_fils = NULL;
- X di->di_flags = 0;
- X return(di);
- X}
- X
- X
- Xstatic DIRINFO *dsearch(v, d)
- X DEVID v;
- X DIRID d;
- X{
- X int i;
- X DIRINFO *di;
- X
- X for(i = 0, di = *dirs; i < ndirs; i++, di++)
- X if (v == di->di_vid && d == di->di_did)
- X return(di);
- X return(NULL);
- X}
- X
- X
- Xstatic int match(pat, s, start1, len1)
- X char *pat, *s, **start1;
- X int *len1;
- X{
- X char c, *olds;
- X
- X *start1 = 0;
- X for(;;)
- X switch (c = *pat) {
- X case '\0':
- X case SLASH:
- X return(*s == '\0');
- X#ifdef MSDOS
- X case '!':
- X *start1 = olds = s;
- X if ((s = strchr(s, '.')) == NULL)
- X return(0);
- X s++;
- X *len1 = s - olds;
- X if ((c = *(++pat)) == '\0') {
- X *len1 += strlen(s);
- X return(1);
- X }
- X for ( ; !match(pat, s, start1 + 1, len1 + 1); (*len1)++, s++)
- X if (*s == '\0')
- X return(0);
- X return(1);
- X#endif
- X case '*':
- X *start1 = s;
- X if ((c = *(++pat)) == '\0') {
- X *len1 = strlen(s);
- X return(1);
- X }
- X else {
- X for (*len1=0; !match(pat, s, start1+1, len1+1); (*len1)++, s++)
- X if (
- X#ifdef MSDOS
- X *s == '.' ||
- X#endif
- X *s == '\0'
- X )
- X return(0);
- X return(1);
- X }
- X case '?':
- X if (
- X#ifdef MSDOS
- X *s == '.' ||
- X#endif
- X *s == '\0'
- X )
- X return(0);
- X *(start1++) = s;
- X *(len1++) = 1;
- X pat++;
- X s++;
- X break;
- X case '[':
- X {
- X int matched = 0, notin = 0, inrange = 0;
- X char prevc = '\0';
- X
- X if ((c = *(++pat)) == '^') {
- X notin = 1;
- X c = *(++pat);
- X }
- X while (c != ']') {
- X if (c == '-' && !inrange)
- X inrange = 1;
- X else {
- X if (c == ESC) {
- X c = *(++pat);
- X }
- X if (inrange) {
- X if (*s >= prevc && *s <= c)
- X matched = 1;
- X inrange = 0;
- X }
- X else if (c == *s)
- X matched = 1;
- X prevc = c;
- X }
- X c = *(++pat);
- X }
- X if (inrange && *s >= prevc)
- X matched = 1;
- X if (!(matched ^ notin))
- X return(0);
- X *(start1++) = s;
- X *(len1++) = 1;
- X pat++;
- X s++;
- X }
- X break;
- X case ESC:
- X c = *(++pat);
- X default:
- X if (c == *s) {
- X pat++;
- X s++;
- X }
- X else
- X return(0);
- X }
- X}
- X
- X
- Xstatic void makerep()
- X{
- X int l, x;
- X#ifndef MSDOS
- X int i, cnv;
- X char *q;
- X#endif
- X char *p, *pat, c, pc;
- X
- X repbad = 0;
- X p = fullrep;
- X for (pat = to, l = 0; (c = *pat) != '\0'; pat++, l++) {
- X if (c == '=') {
- X c = *(++pat);
- X#ifndef MSDOS
- X if (c == 'l') {
- X cnv = LOWER;
- X c = *(++pat);
- X }
- X if (c == 'u') {
- X cnv = UPPER;
- X c = *(++pat);
- X }
- X else
- X cnv = STAY;
- X#endif
- X for(x = 0; ;x *= 10) {
- X x += c - '0';
- X c = *(pat+1);
- X if (!isdigit(c))
- X break;
- X pat++;
- X }
- X --x;
- X if (l + len[x] >= MAXPATH)
- X goto toolong;
- X#ifdef MSDOS
- X if (
- X *(start[x]) == '.' &&
- X (
- X p == fullrep ||
- X *(p - 1) == SLASH
- X )
- X ) {
- X repbad = 1;
- X if (l + STRLEN(EMPTY) >= MAXPATH)
- X goto toolong;
- X strcpy(p, EMPTY);
- X p += STRLEN(EMPTY);
- X l += STRLEN(EMPTY);
- X }
- X#else
- X switch (cnv) {
- X case STAY:
- X#endif
- X memmove(p, start[x], len[x]);
- X p += len[x];
- X#ifndef MSDOS
- X break;
- X case LOWER:
- X for (i = len[x], q = start[x]; i > 0; i--, p++, q++)
- X *p = mylower(*q);
- X break;
- X case UPPER:
- X for (i = len[x], q = start[x]; i > 0; i--, p++, q++)
- X *p = myupper(*q);
- X }
- X#endif
- X }
- X else {
- X if (c == ESC)
- X c = *(++pat);
- X if (l == MAXPATH)
- X goto toolong;
- X if (
- X (
- X#ifdef MSDOS
- X c == '.' ||
- X#endif
- X c == SLASH
- X ) &&
- X (
- X p == fullrep ? pat != to :
- X (
- X (
- X (pc = *(p - 1)) == SLASH
- X#ifdef MSDOS
- X || pc == ':'
- X#endif
- X ) &&
- X *(pat - 1) != pc
- X )
- X )
- X ) {
- X repbad = 1;
- X if (l + STRLEN(EMPTY) >= MAXPATH)
- X goto toolong;
- X strcpy(p, EMPTY);
- X p += STRLEN(EMPTY);
- X l += STRLEN(EMPTY);
- X }
- X *(p++)= c;
- X }
- X }
- X if (p == fullrep) {
- X strcpy(fullrep, EMPTY);
- X repbad = 1;
- X }
- X *(p++) = '\0';
- X return;
- X
- Xtoolong:
- X repbad = 1;
- X strcpy(fullrep, TOOLONG);
- X}
- X
- X
- Xstatic void checkcollisions()
- X{
- X REPDICT *rd, *prd;
- X REP *p, *q;
- X int i, mult, oldnreps;
- X
- X if (nreps == 0)
- X return;
- X rd = (REPDICT *)myalloc(nreps * sizeof(REPDICT));
- X for (
- X q = &hrep, p = q->r_next, prd = rd, i = 0;
- X p != NULL;
- X q = p, p = p->r_next, prd++, i++
- X ) {
- X prd->rd_p = p;
- X prd->rd_dto = p->r_hto->h_di;
- X prd->rd_nto = p->r_nto;
- X prd->rd_i = i;
- X }
- X qsort(rd, nreps, sizeof(REPDICT), rdcmp);
- X mult = 0;
- X for (i = 0, prd = rd, oldnreps = nreps; i < oldnreps; i++, prd++)
- X if (
- X i < oldnreps - 1 &&
- X prd->rd_dto == (prd + 1)->rd_dto &&
- X strcmp(prd->rd_nto, (prd + 1)->rd_nto) == 0
- X ) {
- X if (!mult)
- X mult = 1;
- X else
- X printf(" , ");
- X printf("%s%s", prd->rd_p->r_hfrom->h_name,
- X prd->rd_p->r_ffrom->fi_name);
- X prd->rd_p->r_flags |= R_SKIP;
- X prd->rd_p->r_ffrom->fi_rep = MISTAKE;
- X nreps--;
- X badreps++;
- X }
- X else if (mult) {
- X prd->rd_p->r_flags |= R_SKIP;
- X prd->rd_p->r_ffrom->fi_rep = MISTAKE;
- X nreps--;
- X badreps++;
- X printf(" , %s%s -> %s%s : collision.\n",
- X prd->rd_p->r_hfrom->h_name, prd->rd_p->r_ffrom->fi_name,
- X prd->rd_p->r_hto->h_name, prd->rd_nto);
- X mult = 0;
- X }
- X chgive(rd, oldnreps * sizeof(REPDICT));
- X}
- X
- X
- Xstatic int rdcmp(rd1, rd2)
- X REPDICT *rd1, *rd2;
- X{
- X int ret;
- X
- X if (
- X (ret = rd1->rd_dto - rd2->rd_dto) == 0 &&
- X (ret = strcmp(rd1->rd_nto, rd2->rd_nto)) == 0
- X )
- X ret = rd1->rd_i - rd2->rd_i;
- X return(ret);
- X}
- X
- X
- Xstatic void findorder()
- X{
- X REP *p, *q, *t, *first, *pred;
- X FILEINFO *fi;
- X
- X for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next)
- X if (p->r_flags & R_SKIP) {
- X q->r_next = p->r_next;
- X p = q;
- X }
- X else if (
- X (fi = p->r_fdel) == NULL ||
- X (pred = fi->fi_rep) == NULL ||
- X pred == MISTAKE
- X )
- X continue;
- X else if ((first = pred->r_first) == p) {
- X p->r_flags |= R_ISCYCLE;
- X pred->r_flags |= R_ISALIASED;
- X if (op & MOVE)
- X p->r_fdel = NULL;
- X }
- X else {
- X if (op & MOVE)
- X p->r_fdel = NULL;
- X while (pred->r_thendo != NULL)
- X pred = pred->r_thendo;
- X pred->r_thendo = p;
- X for (t = p; t != NULL; t = t->r_thendo)
- X t->r_first = first;
- X q->r_next = p->r_next;
- X p = q;
- X }
- X}
- X
- X
- Xstatic void nochains()
- X{
- X REP *p, *q;
- X
- X for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next)
- X if (p->r_flags & R_ISCYCLE || p->r_thendo != NULL) {
- X printchain(p);
- X printf("%s%s : no chain copies allowed.\n",
- X p->r_hto->h_name, p->r_nto);
- X q->r_next = p->r_next;
- X p = q;
- X }
- X}
- X
- X
- Xstatic void printchain(p)
- X REP *p;
- X{
- X if (p->r_thendo != NULL)
- X printchain(p->r_thendo);
- X printf("%s%s -> ", p->r_hfrom->h_name, p->r_ffrom->fi_name);
- X badreps++;
- X nreps--;
- X p->r_ffrom->fi_rep = MISTAKE;
- X}
- X
- X
- Xstatic void scandeletes(pkilldel)
- X int (*pkilldel)();
- X{
- X REP *p, *q, *n;
- X
- X for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next) {
- X if (p->r_fdel != NULL)
- X while ((*pkilldel)(p)) {
- X nreps--;
- X p->r_ffrom->fi_rep = MISTAKE;
- X if ((n = p->r_thendo) != NULL) {
- X if (op & MOVE)
- X n->r_fdel = p->r_ffrom;
- X n->r_next = p->r_next;
- X q->r_next = p = n;
- X }
- X else {
- X q->r_next = p->r_next;
- X p = q;
- X break;
- X }
- X }
- X }
- X}
- X
- X
- Xstatic int baddel(p)
- X REP *p;
- X{
- X HANDLE *hfrom = p->r_hfrom, *hto = p->r_hto;
- X FILEINFO *fto = p->r_fdel;
- X char *t = fto->fi_name, *f = p->r_ffrom->fi_name;
- X char *hnf = hfrom->h_name, *hnt = hto->h_name;
- X
- X if (delstyle == NODEL && !(p->r_flags & R_DELOK) && !(op & APPEND))
- X printf("%s%s -> %s%s : old %s%s would have to be %s.\n",
- X hnf, f, hnt, t, hnt, t,
- X (op & OVERWRITE) ? "overwritten" : "deleted");
- X else if (fto->fi_rep == MISTAKE)
- X printf("%s%s -> %s%s : old %s%s was to be done first.\n",
- X hnf, f, hnt, t, hnt, t);
- X else if (
- X#ifdef MSDOS
- X fto->fi_attrib & FA_DIREC
- X#else
- X fto->fi_stflags & FI_ISDIR
- X#endif
- X )
- X printf("%s%s -> %s%s : %s%s%s is a directory.\n",
- X hnf, f, hnt, t, (op & APPEND) ? "" : "old ", hnt, t);
- X#ifndef MSDOS
- X else if ((fto->fi_stflags & FI_NODEL) && !(op & (APPEND | OVERWRITE)))
- X printf("%s%s -> %s%s : old %s%s lacks delete permission.\n",
- X hnf, f, hnt, t, hnt, t);
- X#endif
- X else if (
- X (op & (APPEND | OVERWRITE)) &&
- X#ifdef MSDOS
- X fto->fi_attrib & FA_RDONLY
- X#else
- X !fwritable(hnt, fto)
- X#endif
- X ) {
- X printf("%s%s -> %s%s : %s%s %s.\n",
- X hnf, f, hnt, t, hnt, t,
- X#ifndef MSDOS
- X#ifndef SYSV
- X fto->fi_stflags & FI_LINKERR ?
- X "is a badly aimed symbolic link" :
- X#endif
- X#endif
- X "lacks write permission");
- X }
- X else
- X return(0);
- X badreps++;
- X return(1);
- X}
- X
- X
- Xstatic int skipdel(p)
- X REP *p;
- X{
- X if (p->r_flags & R_DELOK)
- X return(0);
- X fprintf(stderr, "%s%s -> %s%s : ",
- X p->r_hfrom->h_name, p->r_ffrom->fi_name,
- X p->r_hto->h_name, p->r_nto);
- X if (
- X#ifdef MSDOS
- X p->r_fdel->fi_attrib & FA_RDONLY
- X#else
- X#ifndef SYSV
- X !(p->r_ffrom->fi_stflags & FI_ISLNK) &&
- X#endif
- X !fwritable(p->r_hto->h_name, p->r_fdel)
- X#endif
- X )
- X fprintf(stderr, "old %s%s lacks write permission. delete it",
- X p->r_hto->h_name, p->r_nto);
- X else
- X fprintf(stderr, "%s old %s%s",
- X (op & OVERWRITE) ? "overwrite" : "delete",
- X p->r_hto->h_name, p->r_nto);
- X return(!getreply("? ", -1));
- X}
- X
- X
- Xstatic void goonordie()
- X{
- X if ((paterr || badreps) && nreps > 0) {
- X fprintf(stderr, "Not everything specified can be done.");
- X if (badstyle == ABORTBAD) {
- X fprintf(stderr, " Aborting.\n");
- X exit(1);
- X }
- X else if (badstyle == SKIPBAD)
- X fprintf(stderr, " Proceeding with the rest.\n");
- X else if (!getreply(" Proceed with the rest? ", -1))
- X exit(1);
- X }
- X}
- X
- X
- Xstatic void doreps()
- X{
- X char *fstart;
- X int k, printaliased = 0, alias;
- X REP *first, *p;
- X long aliaslen;
- X
- X#ifdef MSDOS
- X ctrlbrk(breakrep);
- X#else
- X signal(SIGINT, breakrep);
- X#endif
- X
- X for (first = hrep.r_next, k = 0; first != NULL; first = first->r_next) {
- X for (p = first; p != NULL; p = p->r_thendo, k++) {
- X if (gotsig) {
- X fflush(stdout);
- X fprintf(stderr, "User break.\n");
- X printaliased = snap(first, p);
- X gotsig = 0;
- X }
- X strcpy(fullrep, p->r_hto->h_name);
- X strcat(fullrep, p->r_nto);
- X if (!noex && (p->r_flags & R_ISCYCLE))
- X if (op & APPEND)
- X aliaslen = appendalias(first, p, &printaliased);
- X else
- X alias = movealias(first, p, &printaliased);
- X strcpy(pathbuf, p->r_hfrom->h_name);
- X fstart = pathbuf + strlen(pathbuf);
- X if ((p->r_flags & R_ISALIASED) && !(op & APPEND))
- X sprintf(fstart, "%s%03d", TEMP, alias);
- X else
- X strcpy(fstart, p->r_ffrom->fi_name);
- X if (!noex) {
- X if (p->r_fdel != NULL && !(op & (APPEND | OVERWRITE)))
- X myunlink(fullrep, p->r_fdel);
- X if (
- X (op & (COPY | APPEND)) ?
- X copy(p->r_ffrom,
- X p->r_flags & R_ISALIASED ? aliaslen : -1) :
- X#ifndef MSDOS
- X (op & HARDLINK) ?
- X link(pathbuf, fullrep) :
- X#ifndef SYSV
- X (op & SYMLINK) ?
- X symlink((p->r_flags & R_ONEDIRLINK) ? fstart : pathbuf,
- X fullrep) :
- X#endif
- X#endif
- X p->r_flags & R_ISX ?
- X copymove(p) :
- X /* move */
- X rename(pathbuf, fullrep)
- X ) {
- X fprintf(stderr,
- X "%s -> %s has failed.\n", pathbuf, fullrep);
- X printaliased = snap(first, p);
- X }
- X }
- X if (verbose || noex) {
- X if (p->r_flags & R_ISALIASED && !printaliased)
- X strcpy(fstart, p->r_ffrom->fi_name);
- X fprintf(outfile, "%s %c%c %s%s%s\n",
- X pathbuf,
- X p->r_flags & R_ISALIASED ? '=' : '-',
- X p->r_flags & R_ISCYCLE ? '^' : '>',
- X fullrep,
- X (p->r_fdel != NULL && !(op & APPEND)) ? " (*)" : "",
- X noex ? "" : " : done");
- X }
- X }
- X printaliased = 0;
- X }
- X if (k != nreps)
- X fprintf(stderr, "Strange, did %d reps; %d were expected.\n",
- X k, nreps);
- X if (k == 0)
- X fprintf(stderr, "Nothing done.\n");
- X}
- X
- X
- Xstatic long appendalias(first, p, pprintaliased)
- X REP *first, *p;
- X int *pprintaliased;
- X{
- X long ret;
- X
- X#ifdef MSDOS
- X int fd;
- X
- X if ((fd = open(fullrep, O_RDONLY | O_BINARY, 0)) < 0) {
- X fprintf(stderr, "stat on %s has failed.\n", fullrep);
- X *pprintaliased = snap(first, p);
- X }
- X else {
- X ret = filelength(fd);
- X close(fd);
- X }
- X#else
- X struct stat fstat;
- X
- X if (stat(fullrep, &fstat)) {
- X fprintf(stderr, "append cycle stat on %s has failed.\n", fullrep);
- X *pprintaliased = snap(first, p);
- X }
- X else
- X ret = fstat.st_size;
- X#endif
- X
- X return(ret);
- X}
- X
- X
- END_OF_FILE
- if test 49841 -ne `wc -c <'mmv.c.1'`; then
- echo shar: \"'mmv.c.1'\" unpacked with wrong size!
- fi
- # end of 'mmv.c.1'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- exit 0 # Just in case...
-